package com.dkts.oil.util;

import org.geotools.referencing.CRS;
import org.geotools.referencing.GeodeticCalculator;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.GeometryFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import java.util.ArrayList;
import java.util.List;

public class GeoGridUtil {

    private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();

    /**
     * 生成规划区域内均匀分布的格子中心点（按球面距离米计算）
     *
     * @param planGeometry    规划区域 Geometry
     * @param gridSizeMeters  格子边长（米）
     * @return 点集合
     * @throws Exception 异常
     */
    public static List<Point> generateGridPoints(Geometry planGeometry, double gridSizeMeters) throws Exception {
        Envelope env = planGeometry.getEnvelopeInternal();
        List<Point> points = new ArrayList<>();

        CoordinateReferenceSystem crs = CRS.decode("EPSG:4326");
        GeodeticCalculator calc = new GeodeticCalculator(crs);

        double startLon = env.getMinX();
        double startLat = env.getMinY();

        double currentLat = startLat;

        // 外层：纬度方向
        while (currentLat <= env.getMaxY()) {
            double currentLon = startLon;

            // 内层：经度方向
            while (currentLon <= env.getMaxX()) {
                Point point = GEOMETRY_FACTORY.createPoint(new Coordinate(currentLon, currentLat));

                if (planGeometry.contains(point)) {
                    points.add(point);
                }

                // 经度方向前进一步
                calc.setStartingGeographicPoint(currentLon, currentLat);
                calc.setDirection(90, gridSizeMeters); // 90° 向东
                currentLon = calc.getDestinationGeographicPoint().getX();
            }

            // 纬度方向前进一步
            calc.setStartingGeographicPoint(startLon, currentLat);
            calc.setDirection(0, gridSizeMeters); // 0° 向北
            currentLat = calc.getDestinationGeographicPoint().getY();
        }

        return points;
    }
}
